package com.kgcx.price.utils;


import com.alibaba.fastjson.JSONObject;
import com.kgcx.common.client.order.OrderClient;
import com.kgcx.common.client.order.pojo.Order;
import com.kgcx.common.client.organization.DriverClient;
import com.kgcx.common.client.organization.pojo.Driver;
import com.kgcx.common.constant.Cons;
import com.kgcx.common.eum.OrderEnum;
import com.kgcx.common.utils.UUIDUtils;
import com.kgcx.core.utils.LngLatUtil;
import com.kgcx.price.domain.MileageLngLat;
import com.kgcx.price.rabbitmq.BaseInfoProducer;
import org.eclipse.paho.client.mqttv3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.util.StringUtils;

/**
 * 发布消息的回调类
 * <p>
 * 必须实现MqttCallback的接口并实现对应的相关接口方法
 * ◦CallBack 类将实现 MqttCallBack。每个客户机标识都需要一个回调实例。在此示例中，构造函数传递客户机标识以另存为实例数据。在回调中，将它用来标识已经启动了该回调的哪个实例。
 * ◦必须在回调类中实现三个方法：
 * <p>
 * public void messageArrived(MqttTopic topic, MqttMessage message)
 * 接收已经预订的发布。
 * <p>
 * public void connectionLost(Throwable cause)
 * 在断开连接时调用。
 * <p>
 * public void deliveryComplete(MqttDeliveryToken token))
 * 接收到已经发布的 QoS 1 或 QoS 2 消息的传递令牌时调用。
 * ◦由 MqttClient.connect 激活此回调。
 */
public class PushCallback implements MqttCallback {

    private StringRedisTemplate stringRedisTemplate;

    private BaseInfoProducer baseInfoProducer;

    private MqttClient mqttClient;

    private DriverClient driverClient;

    private OrderClient orderClient;


    private Logger logger = LoggerFactory.getLogger(this.getClass());

    public PushCallback(StringRedisTemplate stringRedisTemplate, BaseInfoProducer baseInfoProducer, MqttClient mqttClient, DriverClient driverClient, OrderClient orderClient) {
        this.stringRedisTemplate = stringRedisTemplate;
        this.baseInfoProducer = baseInfoProducer;
        this.mqttClient = mqttClient;
        this.driverClient = driverClient;
        this.orderClient = orderClient;
    }

    @Override
    public void connectionLost(Throwable cause) {
        // 连接丢失后，一般在这里面进行重连

        logger.info("连接断开，可以做重连");

        logger.error(" MQTT客户端连接报错：\" with cause \"" + cause.getMessage() + "\" Reason code "
                + ((MqttException) cause).getReasonCode() + "\" Cause \""
                + ((MqttException) cause).getCause() + "\"");
//        if (!mqttClient.isConnected())
//        {
//            try
//            {
//                mqttClient.connect(mqttConnectOptions);
//            }
//            catch (MqttException e)
//            {
//                e.printStackTrace();
//            }
//        }
        if (!mqttClient.isConnected()) {
            try {
                mqttClient.reconnect();
                mqttClient.subscribe("mileageRecordUpload", 1);

                logger.info("客服端重连成功！");
            } catch (MqttException e) {
                e.printStackTrace();
                logger.error("客服端重连失败！！");
            }
        }

    }

    @Override
    public void messageArrived(String s, MqttMessage mqttMessage) throws Exception {
        // subscribe后得到的消息会执行到这里面
        logger.info("接收消息主题:" + s);
        logger.info("接收消息Qos:" + mqttMessage.getQos());
        logger.info("接收消息内容:" + new String(mqttMessage.getPayload()));

        try {
            String payload = new String(mqttMessage.getPayload());

            if (!"close".equals(payload)) {
                JSONObject jsonObject = JSONObject.parseObject(payload);

                /** 数据入redis，用python脚本将坐标信息入库 */
                if (!(StringUtils.isEmpty(jsonObject.getString("driverId")) && StringUtils.isEmpty(jsonObject.getString("lat")) && StringUtils.isEmpty(jsonObject.getString("lng")))) {
                    /** 数据入redis,记录所有上传坐标 */
                    jsonObject.put("kid", UUIDUtils.getOrderSnByTime18());
                    stringRedisTemplate.opsForList().rightPush("mileageRecord_" + jsonObject.getString("driverId"), jsonObject.toJSONString());

                    JSONObject redisJson = JSONObject.parseObject(stringRedisTemplate.opsForValue().get("driver_" + jsonObject.getString("driverId")));

                    Double mileage = 0D;

                    if (redisJson != null) {
                        mileage = LngLatUtil.getDistance(Double.valueOf(jsonObject.getString("lat")), Double.valueOf(jsonObject.getString("lng")), Double.valueOf(redisJson.getString("lat")), Double.valueOf(redisJson.getString("lng")));
                        jsonObject.put("mileage", mileage + redisJson.getDouble("mileage"));
                    } else {
                        jsonObject.put("mileage", mileage);
                    }


                    /** 数据入redis，增量更新，为其他模块查询实时坐标做数据准备 */
                    stringRedisTemplate.opsForValue().set("driver_" + jsonObject.getString("driverId"), jsonObject.toJSONString());

                    MileageLngLat mileageLngLat = jsonObject.toJavaObject(MileageLngLat.class);

                    /** 发送mq消息到监管上送平台，通知监管上送平台将数据提交到监管平台 */
                    mileageLngLat.setWarnStatus(0);
                    mileageLngLat.setVehStatus(0);
                    mileageLngLat.setMileage(mileage.intValue());

                    Driver driver = driverClient.getDriver(jsonObject.getLong("driverId"), null);
                    if (null != driver) {
                        Integer state = driver.getState();
                        if (Cons.DRIVER_STATE_RUN.equals(state)) {
                            Long orderId = mileageLngLat.getOrderId();
                            if (null != orderId) {
                                Order order = orderClient.getByOrderNo(orderId.toString());
                                if (null != order) {
                                    Integer orderState = order.getOrderState();
                                    if (OrderEnum.PASSENGER_GET_IN == orderState || OrderEnum.ON_ROAD == orderState) {
                                        mileageLngLat.setBizStatus(1);
                                    } else {
                                        mileageLngLat.setBizStatus(2);
                                    }
                                }
                            }
                        } else if (Cons.DRIVER_STATE_OFF.equals(state)) {
                            mileageLngLat.setBizStatus(4);
                        } else {
                            mileageLngLat.setBizStatus(3);
                        }
                    }


                    baseInfoProducer.addBaseInfoDriverLocation(mileageLngLat);
                    baseInfoProducer.addBaseInfoCarLocation(mileageLngLat);
                }

            }
        } catch (Exception e) {
            logger.info("mqtt接收消息处理失败");
            logger.error(e.getMessage());
        }
    }

    @Override
    public void deliveryComplete(IMqttDeliveryToken iMqttDeliveryToken) {
        // publish后会执行到这里
        System.out.println("deliveryComplete---------" + iMqttDeliveryToken.isComplete());
    }

}
